package main

import (
	"errors"
	"fmt"
	"go_code/chapter01/model"
	"strconv"
	"strings"
)

var (
	Func1 = func(n1 int, n2 int) int {
		return n1 + n2
	}
)

func fbn(n int) int {
	if n == 1 || n == 2 {
		return 1
	} else {
		return fbn(n-1) + fbn(n-2)
	}
}
func f(n int) int {
	if n == 1 {
		return 3
	} else {
		return 2*f(n-1) + 1
	}
}

func peach(n int) int {
	if n > 10 || n < 1 {
		return 0
	} else {
		if n == 10 {
			return 1
		} else {
			return (peach(n+1) + 1) * 2
		}
	}
}

// AddUpper 累加器
func AddUpper() func(int) int {
	var n = 10
	return func(x int) int {
		n = n + x
		return n
	}
}

// makeSuffix 判断文件名有无指定后缀，
//有则返回文件名全称，无则返回文件名加此后缀
func makeSuffix(suffix string) func(string) string {
	return func(name string) string {
		//判断传入文件名有无后缀
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		} else {
			return name
		}
	}
}

// sumDefer defer延时机制运行说明
func sumDefer(n1 int, n2 int) int {
	// 当执行到defer时，暂时不执行，
	//会将defer后面的语句压入到独立的栈（defer栈）
	defer fmt.Println("ok1 n1=", n1)
	defer fmt.Println("ok2 n2=", n2)

	res := n1 + n2
	fmt.Println("ok3 res = ", res)
	return res
}

func testPanic() {
	// 使用defer+recover 来捕获和处理异常
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err=", err)
		}
	}()
	num1 := 10
	num2 := 0
	res := num1 / num2
	fmt.Println("res=", res)
}

func readConf(name string) (err error) {
	if name == "conf.ini" {
		return nil
	} else {
		return errors.New("读取文件错误...")
	}
}
func test02() {
	err := readConf("config.ini")
	if err != nil {
		// 如果读取文件发送错误，就输出这个错误，并终止程序
		panic(err)
	}
	fmt.Println("test02继续执行...")
}

type Stu struct {
	Name    string
	Age     int
	Address string
}

type Person struct {
	Name string
}

// 给Person类型绑定一方法
func (p Person) test() {
	fmt.Println("test()", p.Name)
}

func main() {
	worker := model.NewPerson("smith")
	worker.SetSal(5000)
	worker.SetAge(19)
	fmt.Println(worker)
	fmt.Println(worker.Name, "age=", worker.GetAge(),
		"sal=", worker.GetSal())

	//stu := model.student{
	//	Name:  "zhangsan",
	//	Score: 99.6,
	//}
	// 通过方法，在堆内存中创建新的实例数据
	stu := model.PublicStudent("tomm", 89.89) //报错
	//stu := model.PublicStudent("tomm",88.89)
	fmt.Println(stu.GetScore())

	//返回的是指针：&{} 需要使用*进行取值
	fmt.Println(stu)

	var p2 = Person{"tom"}
	//调用方法
	p2.test()
	p3 := Person{"tom2"}
	p3.test()
	// 标明字段名称的写法不再依赖顺序
	p4 := Person{
		Name: "tom2",
	}
	p4.test()

	// 返回结构体指针类型
	var p5 = &Person{
		Name: "zhangsan",
	}
	//带*符将它的值从空间里拿到，否则返回出来的带&号
	(*p5).test()

	students := make(map[string]Stu)
	stu1 := Stu{"tom", 18, "北京"} //注意用{}
	stu2 := Stu{"mary", 21, "上海"}
	students["no1"] = stu1
	students["no2"] = stu2
	fmt.Println(students)

	for k, v := range students {
		fmt.Printf("学生的编号是%v\n", k)
		fmt.Printf("学生的名字是%v\n", v.Name)
		fmt.Printf("学生的年龄是%v\n", v.Age)
		fmt.Printf("学生的地址是%v\n", v.Address)
	}

	/*n1 := 2
	n2 := 3
	n3 := n1 + n2


	fmt.Println(n1)
	fmt.Println(n2)
	fmt.Println(n3)

	fmt.Println(model.TestModelName)
	// 取模运算%
	fmt.Println("10 % 3 = ", 10 % 3)//1
	fmt.Println("-10 % 3 = ", -10 % 3)//-1
	fmt.Println("10 % -3 = ", 10 % -3)//1
	fmt.Println("-10 % -3 = ", -10 % -3)//-1

	//一共97天，问：有多少个星期，零几天
	x := 97
	week := x / 7
	day := x % 7
	fmt.Printf("有 %v 个星期，%v 天", week, day)//-1
	a := 10
	b := 20
	a = a + b
	b = a - b //b = a + b - b ==>b = a
	a = a - b //a = a + b ,a是总和，b是a，所以a=b
	fmt.Printf("a: %v,b: %v", a, b)*/

	// 从键盘输入
	/*var name string
	var age byte
	var sal float32
	var isPass bool*/
	/*fmt.Println("请输入姓名：")
	fmt.Scanln(&name)
	fmt.Println("请输入年龄：")
	fmt.Scanln(&age)

	fmt.Println("请输入薪水：")
	fmt.Scanln(&sal)

	fmt.Println("是否通过考试：")
	fmt.Scanln(&isPass)*/

	/*fmt.Scanf("%s %d %f %t",&name ,&age ,&sal ,&isPass)
	fmt.Printf("名字是 %v ,年龄是 %v，薪水是 %v，是否通过考试：%v",
		name, age, sal, isPass)*/
	/*var key float64
	fmt.Scanln(&key)
	fmt.Println(key)
	switch int(key / 60) {
	case 1:
		fmt.Println("及格")
	case 0:
		fmt.Println("不及格")
	default:
		fmt.Println("输入有误")
	}*/

	/*	for i := 0; i < 10; i++ {
		fmt.Println("测试", i)
	}*/

	/*j := 0
	for j < 5 {
		fmt.Println("sss",j)
		j++
	}*/
	/*i := 1
	for {// 这里等价于for ; ;{}
		if i <= 5 {
			fmt.Println("ss")
		}else {
			break
		}
		i++
	}*/

	//传统方式遍历字符串
	//str := "hello"
	//for i:=0; i<len(str); i++{
	//	fmt.Printf("输出：%c \n",str[i])
	//}

	//传统遍历，改进
	/*str := "hello背景"
	str2 := []rune(str)
	for i:=0; i<len(str2); i++{
		fmt.Printf("输出：%c \n",str2[i])
	}*/

	//for-range方式遍历
	/*for index, val := range str{
		fmt.Printf("index=%d val=%c\n", index, val)
	}*/

	//层数：5
	/*var num int = 5
	for i := 1 ; i <= num; i++ {
		for k := 1; k <= num - i; k++ {
			fmt.Printf(" ")
		}
		for j := 1; j <= 2*i-1; j++ {
			//fmt.Printf("*")
			if j == 1 || j == 2*i-1 || i == num{
				fmt.Printf("*")
			}else {
				fmt.Printf(" ")
			}
		}
		fmt.Println()
	}*/

	//九九乘法表
	/*for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%v * %v = %v \t", j, i, j*i)
		}
		fmt.Println()
	}*/
	/*var count int = 0
	for{
		// time.Now().Unix()返回一个从1970:1:1到现在所经过的秒数
		rand.Seed(time.Now().UnixNano())
		n := rand.Intn(100) + 1
		count ++
		if n == 20{
			break
		}
	}
	fmt.Println(count)*/
	/*label:
	for i := 0; i < 5; i++ {
		for j := 0; j < 6;j++{
			if j == 2 {
				break label
			}
			fmt.Println("j=",j)
		}
	}*/
	/*	goto label2
			fmt.Println("ok1")
			fmt.Println("ok2")
			fmt.Println("ok3")
		label2:
			fmt.Println("ok4")
			fmt.Println("ok5")
			fmt.Println("ok6")*/
	/*fmt.Println("res=", fbn(1))
	fmt.Println("res=", fbn(2))
	fmt.Println("res=", fbn(3))
	fmt.Println("res=", fbn(4))
	fmt.Println("res=", fbn(5))
	fmt.Println("res=", fbn(6))

	fmt.Println("f(1)=", f(1))
	fmt.Println("f(2)=", f(2))
	fmt.Println("f(3)=", f(3))*/

	fmt.Println(peach(10))

	testModel := model.TestModelName
	fmt.Println(testModel)

	//定义匿名函数，在定义时直接使用
	res1 := func(n1 int, n2 int) int {
		return n1 + n2
	}(0, 20)

	a := func(n1 int, n2 int) int {
		return n1 - n2
	}
	res2 := a(0, 20)
	fmt.Println(res2)

	res3 := Func1(0, 20)
	fmt.Println(res3)

	fmt.Println(res1)

	f := AddUpper()
	fmt.Println(f(1))
	fmt.Println(f(3))

	make := makeSuffix(".jpg")
	str3 := make("winter.jpg")
	str4 := make("winter22")
	fmt.Println(str3)
	fmt.Println(str4)

	res4 := sumDefer(10, 20)
	fmt.Println("res4=", res4)

	n, err := strconv.Atoi("12")
	if err == nil {
		fmt.Println("err:", n)

	} else {
		fmt.Println("err:", err)

	}
	//测试test（）
	testPanic()
	/*for  {
		if i == 99 {
			break
		}
		fmt.Println("ce.....")
		time.Sleep(time.Millisecond)
		i++
	}*/
	test02()
}
